package config

import (
	"encoding/json"
	"log"
	"net/url"
	"os"

	"code.google.com/p/gomonitor/tsdb"
)

type Location url.URL

func (l *Location) UnmarshalJSON(bs []byte) error {
	s := string(bs[1 : len(bs)-1])
	log.Printf("Unmarshaling %q to url", s)
	u, err := url.Parse(s)
	if err == nil {
		*l = Location(*u)
	}
	return err
}

func (l *Location) Url() *url.URL {
	u := (url.URL)(*l)
	return &u
}

type Config struct {
	Specs      []*ScrapeSpec
	Collectors []*CmdSpec
}

func (c *Config) Metrics() (ms []tsdb.Metric) {
	for _, s := range c.Specs {
		for v, _ := range s.Vars {
			ms = append(ms, tsdb.Metric{s.Name, v})
		}
	}
	for _, c := range c.Collectors {
		for v, _ := range c.Vars {
			ms = append(ms, tsdb.Metric{c.Name, v})
		}
	}
	return
}

type CmdSpec struct {
	Name string
	// Name of the binary to launch
	Bin string
	// Arguments if any to pass to the binary
	Args []string
	// dotted notation for deep variables
	Vars map[string]string
}

type ScrapeSpec struct {
	Name string
	U    Location
	// dotted notation for deep variables
	Vars map[string]string
	// FEATURE alerts?
}

func Read(file string) (*Config, error) {
	c := new(Config)
	err := readJsonFile(file, c)
	if err != nil {
		return nil, err
	}
	return c, nil
}

func readJsonFile(file string, val interface{}) error {
	log.Println("Reading config file:", file)
	f, err := os.Open(file)
	if err != nil {
		return err
	}
	defer f.Close()
	err = json.NewDecoder(f).Decode(val)
	if err != nil {
		return err
	}
	return nil
}
